package com.mark.tim.kutspel;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;

public class PlayView  extends SurfaceView implements SurfaceHolder.Callback {

	private static final String TAG = "PlayView";
	private GameTimer gameTimer;
	private static final int PLANE_WIDTH = 117;
	private static final int PLANE_HEIGHT = 150;
//	private static final int BULLET_WIDTH = 11;
//	private static int BULLET_HEIGHT = 60;
	private static final int ENEMY_WIDTH = 150;
	private static final int ENEMY_HEIGHT = 112;
	private static final int PLANE_MARGIN = 50;
	private static final int ENEMY_HP = 100;
	private static final int DAMAGE = 35;
	private static float factor;

	private Plane plane;
	private Context context;
	private Paint paint;
	private Point size;
	private Rect planeRect;

	private ArrayList<Bullet> visibleBullets;
	private ArrayList<Bullet> removeBullets;
	private ArrayList<Enemy> visibleEnemies;
	private ArrayList<Enemy> removeEnemies;

	private int bulletLevel = 0;
	private int delay = 10;
	private int planeSpeed = 0;
	private int numFPS = 60;

	private Timer enemyTimer;

	public PlayView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		Log.d(TAG, "PlayView loaded");
		gameTimer = new GameTimer(this);
		visibleBullets = new ArrayList<Bullet>();
		removeBullets = new ArrayList<Bullet>();
		visibleEnemies = new ArrayList<Enemy>();
		removeEnemies = new ArrayList<Enemy>();
		paint = new Paint();
		WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
		Display d = wm.getDefaultDisplay();
		size = new Point();
		d.getSize(size);
		enemyTimer = new Timer();

		factor = (size.x / 1080f);
		getHolder().addCallback(this);
	}

	private void appendBullet() {
		long xx = System.currentTimeMillis();
		int y = (int) (size.y - plane.getWidth() - factor * 50);
		if (bulletLevel == 0) {
			int x = (int) (plane.getX() + plane.getWidth() / 2);
			visibleBullets.add(new Bullet(15, x, y));
		} else if (bulletLevel == 1) {
			int x = (int) (plane.getX() + plane.getWidth() / 5);
			visibleBullets.add(new Bullet(15, x, y));
			x = (int) (plane.getX() + plane.getWidth() * 4 / 5);
			visibleBullets.add(new Bullet(15, x, y));
		}
		if (MainActivity.D)Log.d("appendbullettime", "" + (System.currentTimeMillis() - xx));
	}

	public class appendEnemy extends TimerTask {
		@Override
		public void run() {
			synchronized (visibleEnemies) {
				int Enemy_Width = (int) (ENEMY_WIDTH * factor);
				int Enemy_Height = (int) (ENEMY_HEIGHT * factor);
				int x = Enemy_Width / 2	+ (int) (Math.random() * (size.x - Enemy_Width));
				Log.d("random", "" + x);
				int y = -Enemy_Height;
				int speed = 6 + (int) (Math.random() * 5);
				Log.d("randspeed", "" + speed);
				
				visibleEnemies.add(new Enemy(speed, x, y, ENEMY_HP));
				enemyTimer.schedule(new appendEnemy(), (long) (1000 + 1000 * Math.random()));
			}
		}
	}

	public void collisionDetection() {
		for (Enemy e : visibleEnemies) {
			for (Bullet b : visibleBullets) {
				if(e.getRect().bottom > b.getRect().top &&
				   e.getRect().top < b.getRect().top    &&
				   e.getRect().left < b.getRect().left  &&
				   e.getRect().right > b.getRect().right ) {
					removeBullets.add(b);
					e.setHPleft(e.getHPleft()-DAMAGE);
					if(e.getHPleft() <= 0) {
						removeEnemies.add(e);
					}
				}
			}
		}
		visibleEnemies.removeAll(removeEnemies);
		visibleBullets.removeAll(removeBullets);
	}

	public void setBulletLevel(int bulletLevel) {
		this.bulletLevel = bulletLevel;
	}

	public int getBulletLevel() {
		return bulletLevel;
	}

	public void setDelay(int delay) {
		this.delay = delay;
	}

	public int getDelay() {
		return delay;
	}

	public static float getFactor() {
		return factor;
	}

	public void setPlane(Plane plane) {
		this.plane = plane;
		planeRect = new Rect();

		plane.setWidth((int) (PLANE_WIDTH * factor));
		plane.setHeight((int) (PLANE_HEIGHT * factor));
		plane.setMargin((int) (PLANE_MARGIN * factor));

		planeRect.left = plane.getX();
		planeRect.top = (int) (size.y - plane.getWidth() - plane.getMargin());
		planeRect.right = plane.getX() + plane.getWidth();
		planeRect.bottom = (int) (size.y - plane.getHeight() - plane.getMargin() + plane.getHeight());
//		enemyTimer.schedule(new appendEnemy(), 2000);
	}

	public void setSpeed(int planeSpeed) {
		this.planeSpeed = planeSpeed;
	}

	public void startTimer() {
		gameTimer = new GameTimer(this);
		gameTimer.start();
		enemyTimer = new Timer();
		enemyTimer.schedule(new appendEnemy(), 1500);
	}

	public void stopTimer() {
		gameTimer.stopTimer();
		enemyTimer.cancel();
	}
	
	public void resetValues() {
		bulletLevel = 0;
		delay = 10;
		planeSpeed = 0;
		numFPS = 60;
		visibleBullets = new ArrayList<Bullet>();
		removeBullets = new ArrayList<Bullet>();
		visibleEnemies = new ArrayList<Enemy>();
		removeEnemies = new ArrayList<Enemy>();
		plane.setX(100);
		plane.setY(100);
		MainActivity.debug = false;
	}

	public void movePlane(int amount) {
		if (plane.getX() - amount > 0 && plane.getX() + plane.getWidth() - amount < size.x) {
			setPlanePosition(amount);
		} else if (plane.getX() - amount < 0) {
			setPlanePosition(plane.getX());
		} else if (plane.getX() + plane.getWidth() - amount > size.x) {
			setPlanePosition(-size.x + plane.getWidth() + plane.getX());
		}

		if (MainActivity.D)
			Log.d(TAG, plane.getX() + "");
	}

	public void setPlanePosition(int x) {
		plane.setX(plane.getX() - x);
		planeRect.left = plane.getX();
		planeRect.right = plane.getX() + plane.getWidth();
		planeRect.top = (int) (size.y - plane.getHeight() - factor * 50);
		planeRect.bottom = (int) (size.y - factor * 50);
	}

	@Override
	protected void onDraw(Canvas c) {
		c.drawColor(Color.WHITE);
		synchronized (visibleBullets) {
			for (Bullet b : visibleBullets) {
				c.drawBitmap(Tools.getBulletImage(context), null, b.getRect(), paint);
			}
		}
		synchronized (visibleEnemies) {
			for (Enemy e : visibleEnemies) {
				c.drawBitmap(Tools.getEnemyImage(context), null, e.getRect(), paint);
			}
		}
		c.drawBitmap(Tools.getPlaneImage(context), null, planeRect, paint);
	}

	private class GameTimer extends Thread {
		private long startTime;
		private long endTime;
		private PlayView canvas;
		private SurfaceHolder surfaceHolder = null;
		private boolean stop = false;
		
		public GameTimer(PlayView canvas) {
			super();
			this.canvas = canvas;
			this.surfaceHolder = canvas.getHolder();
		}

		public void stopTimer() {
			stop = true;
		}

		public void run() {
			if (MainActivity.D)Log.d("GameTimer", "GameTimer loaded");
			int localVariable = 0;
			Canvas c = null;
			while (true) {
				c = null;
				if (stop) return;

				startTime = (int) System.nanoTime();
				movePlane(planeSpeed);
				if (localVariable < delay) localVariable++;
				else {
					synchronized (visibleBullets) {
						appendBullet();
					}
					localVariable = 0;
				}

				synchronized (visibleBullets) {
					removeBullets.removeAll(removeBullets);
					for (Bullet b : visibleBullets) {
						Rect rect = b.getRect();
						if (rect.bottom < 0) {
							removeBullets.add(b);
						} else {
							rect.top -= b.getSpeed();
							rect.bottom -= b.getSpeed();
							b.setRect(rect);
						}
					}
					visibleBullets.removeAll(removeBullets);
				}
				synchronized (visibleEnemies) {
					for (Enemy e : visibleEnemies) {
						Rect rect = e.getRect();
						if (rect.top > size.y) {
							removeEnemies.add(e);
						} else {
							rect.top += e.getSpeed();
							rect.bottom += e.getSpeed();
							e.setRect(rect);
						}
					}
					visibleEnemies.removeAll(removeEnemies);
				}

				synchronized (visibleBullets) {
					synchronized (visibleEnemies) {
						collisionDetection();
					}
				}

				try {
					c = surfaceHolder.lockCanvas();
					synchronized (surfaceHolder) {
						if(c != null) {
							canvas.onDraw(c);
						}
					}
				}catch(Exception e){}
				
				finally {
					if (c != null) {
						surfaceHolder.unlockCanvasAndPost(c);
					}
				}
				
				endTime = (int) System.nanoTime();
				if (MainActivity.D) Log.d("GameTimer", "time:" + (endTime - startTime) / 1000000);
				try {
					int sleepTime = 1000000 * (1000 / numFPS) - (int) (endTime - startTime);
					Thread.sleep(sleepTime / 1000000, sleepTime & 1000000);
				} catch (Exception e) {}
			}
		}
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (MainActivity.D)Log.d("Touch", "Touched the screen");
		}
		return super.onTouchEvent(event);
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
	}
}
